#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <time.h>
#include "controlDevice.h"
#include "inputCommand.h"
#include "msg_queue.h"
#include "face.h"
#include "voice.h"
#include "dht11.h"

mqd_t mqd = -1; // 消息队列

struct controlDevice *phead = NULL;
struct controlDevice *pdevice = NULL;

struct inputCommand *commandPhead = NULL;
struct inputCommand *commandPdevice = NULL;

struct inputCommand *socketHandler = NULL; //
int new_socket;

void *voice_Thread(void *datas)
{
    struct inputCommand *voiceHandler;
    int initCount = 0;
    int nread = 0;
    voiceHandler = findInputCommandByName("voiceDevice", commandPhead);
    if (voiceHandler == NULL)
    {
        printf("find voiceHandler error\n");
        pthread_exit(NULL);
    }
    else
    {
        printf("voiceHandler init start:%s\n", voiceHandler->commandName);
        while (voiceHandler->Init(voiceHandler, NULL, NULL, 9600) < 0)
        {
            printf("voice init error\n");
            initCount++;
            sleep(5);
            if (initCount >= 3)
                pthread_exit(NULL);
            continue;
        }
        printf("%s init ok voicehandler\n", voiceHandler->commandName);
        while (1)
        {
            nread = voiceHandler->getCommand(voiceHandler, NULL);
            if (nread == 0)
            {
                // printf("nodata from voice\n");
            }
            else
            {
                printf("do divece control:%s\n", voiceHandler->command); // 09 08 01 00 08 09
                if (nread == 6 && voiceHandler->command[0] == 0x09 && voiceHandler->command[1] == 0x08 && voiceHandler->command[4] == 0x08 && voiceHandler->command[5] == 0x09)
                {
                    if ((send_message(mqd, (void *)voiceHandler->command, nread)) == -1)
                    {
                        printf("send faild\n");
                    }
                    else
                        printf("voice commite to msg_queue,%d\n,", voiceHandler->command[0] == '9');
                    // mq_receive(mqd,voiceHandler->command,nread,NULL);
                }
            }
        }
    }
}

void *read_Thread(void *datas)
{
    socketHandler->getCommand(socketHandler, (char *)&mqd);
    pthread_exit(0);
}

void *socket_Thread(void *datas)
{
    pthread_t readThread;

    int nread = 0;
    struct sockaddr_in address;
    memset(&address, 0, sizeof(struct sockaddr_in));
    int addrlen = sizeof(struct sockaddr_in);

    socketHandler = findInputCommandByName("socketDevice", commandPhead);
    if (socketHandler == NULL)
    {
        printf("find socketHandler error\n");
        pthread_exit(NULL);
    }
    else
    {
        printf("%s init success\n", socketHandler->commandName);
    }
    int bit = socketHandler->Init(socketHandler, NULL, NULL, 9898);
    if (bit != -1)
        pthread_create(&readThread, NULL, read_Thread, NULL);
}

// 线程处理函数
void *handle_device(void *datas)
{
    pthread_detach(pthread_self()); // 分离线程
    printf("处理函数线程\n");

    recv_msg_t *recv_msg = NULL;
    if (datas != NULL)
    {
        recv_msg = (recv_msg_t *)datas;
        printf("传递数据\n");
    }

    printf("recv_msg_buffer:%s\n", recv_msg->buffer);
    if (NULL != recv_msg && NULL != recv_msg->buffer)
    {
        printf("进入switch,buffer[2]=%x\n", recv_msg->buffer[2]);
        switch (recv_msg->buffer[2])
        {
        case 0x01:
            if ((pdevice = findDeviceByName("livingLight", phead)) != NULL)
            {

                if (recv_msg->buffer[3] == 0x00)
                {
                    pdevice->close();
                    printf("客厅灯关灯\n");
                }
                else if (recv_msg->buffer[3] == 0x01)
                {
                    pdevice->open();
                    printf("客厅灯开灯\n");
                }
            }
            break;
        case 0x02:
            if ((pdevice = findDeviceByName("floorLight", phead)) != NULL)
            {
                if (recv_msg->buffer[3] == 0x00)
                {
                    pdevice->close();
                    printf("关闭\n");
                }
                else if (recv_msg->buffer[3] == 0x01)
                {
                    pdevice->open();
                    printf("打开\n");
                }
            }
            break;
        case 0x03:
            if ((pdevice = findDeviceByName("fans", phead)) != NULL)
            {
                if (recv_msg->buffer[3] == 0x00)
                {
                    pdevice->close();
                    printf("关闭风扇\n");
                }
                else if (recv_msg->buffer[3] == 0x01)
                {
                    pdevice->open();
                    printf("开启风扇\n");
                }
            }
            break;
        case 0x04:
            if ((pdevice = findDeviceByName("lock", phead)) != NULL)
            {
                if (recv_msg->buffer[3] == 0x00)
                {
                    pdevice->close();
                    printf("关闭锁\n");
                }
                else if (recv_msg->buffer[3] == 0x01)
                {
                    // 人脸识别
                    char result[128] = {0};
                    char str_part[64];
                    unsigned char voice_buf[7] = {0x09, 0x08, 0x0C, 0x00, 0x08, 0x09};
                    double num;
                    pthread_t voice_setpid;
                    get_face_source(result);
                    printf("func= %s|result = %s\r\n", __func__, result); // hyx,96.02661895751953
                    int parsed = sscanf(result, "%63[^,],%lf", str_part, &num);
                    printf("name:%s|source = %.2f\r\n", str_part, num);
                    // 检查是否成功解析两部分
                    if (parsed != 2)
                    {
                        printf("解析失败：格式错误\n");
                        pthread_exit(0);
                    }
                    if (num >= 70)
                    {
                        pdevice->open();
                        printf("打开锁\n");
                        pthread_create(&(voice_setpid), NULL, voice_set, (void *)voice_buf);
                        sleep(5);
                        pdevice->close();
                        printf("关闭锁\n");
                    }
                    else
                    {
                        printf("人脸识别失败\r\n");
                        voice_buf[2] = 0x0D;
                        pthread_create(&(voice_setpid), NULL, voice_set, (void *)voice_buf);
                    }
                }
            }
            break;
        case 0x05:
            // 获取温度
            pthread_t dht11_getpid;

            if ((commandPdevice = findInputCommandByName("voiceDevice", commandPhead)) != NULL)
            {
                // 获取温度
                printf("获取温湿度\r\n");
                pthread_create(&(dht11_getpid), NULL, dht11Get, (void *)&(commandPdevice->fd));
            }
            break;

        case 0x06:
            // 烟雾报警
            if ((pdevice = findDeviceByName("deep", phead)) != NULL)
            {
                if (recv_msg->buffer[3] == 0x00)
                {
                    pdevice->close();
                    printf("关闭警报\n");
                }
                else if (recv_msg->buffer[3] == 0x01)
                {
                    pdevice->open();
                    printf("开启警报\n");
                }
            }
            break;

        default:
            printf("没有该设备\n");
        }
    }
    printf("结束线程\n");
    free(recv_msg);
    pthread_exit(0);
}

// 消息队列接收线程
void *msg_Thread(void *datas)
{
    printf("消息队列接收线程\n");
    recv_msg_t *recv_msg = NULL;

    pthread_t tid; // 处理线程
    char buffer[1024] = {0};
    ssize_t read_len = -1;
    pthread_detach(pthread_self()); // 分离线程
    while (1)
    {
        memset(buffer, '\0', sizeof(buffer));
        read_len = mq_receive(mqd, buffer, sizeof(buffer), NULL);
        printf("%s|%s|%d:send:%d|%d,read_len=%d\n", __FILE__, __func__, __LINE__, buffer[2],buffer[3], read_len);
        if (-1 == read_len)
        {
            if (errno == EAGAIN)
            {
                printf("queue is empyt\n");
            }
            else
            {
                perror("receive");
                break;
            }
        }
        else if (buffer[0] == 0x09 && buffer[1] == 0x08 && buffer[5] == 0x09 && buffer[4] == 0x08)
        {
            recv_msg = (recv_msg_t *)malloc(sizeof(recv_msg_t));
            memcpy(recv_msg->buffer, buffer, read_len);
            pthread_create(&(tid), NULL, handle_device, (void *)recv_msg);
        }
    }
    pthread_exit(0);
}

int main()
{
    pthread_t voice_thread;
    pthread_t socket_thread;
    pthread_t msg_receive_thread;
    pthread_t smoke_get_thread;

    // 初始化
    if (-1 == wiringPiSetup())
    {
        perror("wiringPi\n");
        return -1;
    }

    // 创建posix消息队列
    mqd = msg_queue_create(); //
    if (mqd == -1)
    {
        perror("create\n");
        return -1;
    }
    printf("msg_queue create success->:/dev/mqueue\n");

    // 添加设备链表
    phead = addLivingRoomToDeviceLink(phead);
    phead = addFloorLightToDeviceLink(phead);
    phead = addFansToDeviceLink(phead);
    phead = addLockToDeviceLink(phead);
    phead = addFireToDeviceLink(phead);
    phead = adddeepToDeviceLink(phead);
    phead = adddht11ToDeviceLink(phead);

    // 添加输入设备
    commandPhead = addVoiceToInputCommandLink(commandPhead);
    commandPhead = addSocketToInputCommandLink(commandPhead);

    // 初始化设备链表
    pdevice = phead;
    while (pdevice != NULL)
    {
        pdevice->deviceInit();
        pdevice = pdevice->Next;
    }

    // 初始化输入端链表
    // commandPdevice = commandPhead;
    // if(commandPdevice != NULL)
    // {
    //     commandPdevice->Init(commandPdevice,NULL ,NULL , 9600);
    // }

    // 输出设备链表所有设备
    printf("==============ALL DEVICE==============\n");
    pdevice = phead;
    while (pdevice != NULL)
    {
        printf("name:%s | pin:%d | pinStatus:%d\n", pdevice->name, pdevice->pin, pdevice->pinStatus);
        pdevice = pdevice->Next;
    }
    printf("======================================\n");

    // 输出输出端链表所有设备
    printf("==============ALL INPUT COMMAND==============\n");
    commandPdevice = commandPhead;
    while (commandPdevice != NULL)
    {
        printf("commandName:%s\n", commandPdevice->commandName);
        commandPdevice = commandPdevice->Next;
    }
    printf("======================================\n");

    // pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
    pthread_create(&voice_thread, NULL, voice_Thread, NULL);
    pthread_create(&socket_thread, NULL, socket_Thread, NULL);
    pthread_create(&msg_receive_thread, NULL, msg_Thread, NULL); // 消息队列线程
    if ((pdevice = findDeviceByName("fire", phead)) != NULL)
    {
        pthread_create(&smoke_get_thread, NULL, pdevice->get, (void *)&mqd);
    }

    pthread_join(voice_thread, NULL);
    pthread_join(socket_thread, NULL);
    pthread_join(msg_receive_thread, NULL);

    return 0;
}